#include "stdafx.h"
#include "InsertPage.h"
#include "ui_MainWindow.h"
#include "InsertPage.h"

using namespace std;
using namespace AirCrash::Calypso;

InsertPage::InsertPage() : mUi(0), mPhotoThread(new PhotoThread()), mInsertThread(new InsertItemThread()),
		mGenerateThread(new GenerateCodesThread()), mValidator(new QIntValidator()) {
	
	connect( mPhotoThread, SIGNAL(imageReady(QIcon, QString)), this, SLOT(imageReady(QIcon, QString)) );
	connect( mInsertThread, SIGNAL(itemInserted()), this, SLOT(itemInserted()) );
	connect( mGenerateThread, SIGNAL(codesGenerated()), this, SLOT(codesGenerated()) );

	if (!QDir("items").exists()) {
		QDir().mkdir("items");
	}
	if (Config::get("Settings", "backupImages").toBool() && !QDir("backup").exists()) {
		QDir().mkdir("backup");
	}
}

InsertPage::~InsertPage() {
	mPhotoThread->interrupt();
	mPhotoThread->wait();
	delete mPhotoThread;
	mInsertThread->wait();
	delete mInsertThread;
	mGenerateThread->wait();
	delete mGenerateThread;

	delete mValidator;
}

void InsertPage::keyPressEvent(QKeyEvent * e) {
}

void InsertPage::paintEvent(QPaintEvent * e) {
}

void InsertPage::showEvent(QShowEvent * e) {
	if (mUi) {
		mUi->mMenuBar->setVisible(true);
		mUi->mInsertMenu->setEnabled(true);
		refreshImages();
	}
}

void InsertPage::hideEvent(QHideEvent * e) {
	if (mUi) {
		mUi->mInsertMenu->setEnabled(false);
	}
}

void InsertPage::setUi(Ui::MainWindowClass * ui) {
	mUi = ui;
	connect( mUi->mInsertItem, SIGNAL(pressed()), this, SLOT(insert()) );
	connect( mUi->mGenerateCodes, SIGNAL(triggered()), this, SLOT(generateCodes()) );
	connect( mUi->mRenewImages, SIGNAL(triggered()), this, SLOT(refreshImages()) );
	connect( mUi->mAddPhotos, SIGNAL(triggered()), this, SLOT(addPhotos()) );

	mUi->mFriday->setValidator(mValidator);
	mUi->mFriday->setText("0");
	mUi->mSaturday->setValidator(mValidator);
	mUi->mSaturday->setText("0");
	mUi->mSunday->setValidator(mValidator);
	mUi->mSunday->setText("0");
}

void InsertPage::refreshImages() {
	qDebug() << "Renew the images";
	mUi->mImages->clear();
	mPhotoThread->start();
}

void InsertPage::imageReady(QIcon icon, QString fileName) {
	QListWidgetItem * listItem = new QListWidgetItem(icon, fileName);
	mUi->mImages->addItem(listItem);
}

void InsertPage::insert() {
	if (!mUi->mInsertInfo->text().isEmpty() && !mUi->mFriday->text().isEmpty() && !mUi->mSaturday->text().isEmpty() &&
			!mUi->mSunday->text().isEmpty()) {

		if (Config::get("Settings", "webcamEnabled").toBool()) {
			QImage camImage(mUi->mOpenCvWidget->getImage());
			if (!camImage.isNull()) {
				qDebug() << "Insert new item";
				mUi->mInsertItem->setEnabled(false);
				mInsertThread->insertItem(mUi->mInsertInfo->text(), camImage, mUi->mFriday->text().toInt(), 
					mUi->mSaturday->text().toInt(), mUi->mSunday->text().toInt(), mUi->mJackpot->isChecked());
			} else {
				emit nextItem();
			}
		} else if (!mUi->mImages->selectedItems().isEmpty()) {
			qDebug() << "Insert new item";

			mUi->mInsertItem->setEnabled(false);
			QListWidgetItem * currentItem = mUi->mImages->takeItem(mUi->mImages->currentRow());

			mInsertThread->insertItem(mUi->mInsertInfo->text(), currentItem->text(), mUi->mFriday->text().toInt(), 
				mUi->mSaturday->text().toInt(), mUi->mSunday->text().toInt(), mUi->mJackpot->isChecked());

			delete currentItem;
		}

		mUi->mImages->clearSelection();
		mUi->mInsertInfo->clear();
		mUi->mFriday->setText("0");
		mUi->mSaturday->setText("0");
		mUi->mSunday->setText("0");
		mUi->mJackpot->setChecked(false);
	}
}

void InsertPage::generateCodes() {
	QSqlQuery query("SELECT COUNT(Id) as numCodes FROM Codes");
	qDebug() << "First: " << query.first();
	int numCodes(query.value(0).toInt());
	if (numCodes > 0 && !Config::get("Simulation", "enabled").toBool()) {
		QMessageBox removeCodes;
		removeCodes.setText("Wil je " + QString::number(numCodes) + " codes wissen?");
		removeCodes.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
		removeCodes.setDefaultButton(QMessageBox::No);
		int chosenButton = removeCodes.exec();
		if (chosenButton == QMessageBox::No) {
			return;
		}
	}

	qDebug() << "Generate codes";
	mUi->mMainWidget->setEnabled(false);
	mGenerateThread->start();	
}

void InsertPage::codesGenerated() {
	mUi->mMainWidget->setEnabled(true);
}

void InsertPage::itemInserted() {
	mUi->mInsertItem->setEnabled(true);
	emit nextItem();
}

void InsertPage::fillInsertPage( int friday, int saturday, int sunday, QString summary, bool jackpot ) {
	mUi->mFriday->setText(QString::number(friday));
	mUi->mSaturday->setText(QString::number(saturday));
	mUi->mSunday->setText(QString::number(sunday));
	mUi->mInsertInfo->setText(summary);
	mUi->mJackpot->setChecked(jackpot);
}

void InsertPage::createItem() {
	mUi->mInsertItem->click();
}

void InsertPage::addPhotos() {
	QFileDialog dialog;
	dialog.setFilter("Image Files (*.png *.jpg *.bmp)");
	dialog.setFileMode(QFileDialog::ExistingFiles);
	if (dialog.exec()) {
		QStringList files(dialog.selectedFiles());
		foreach(QString filePath, files) {
			QFileInfo file(filePath);
			qDebug() << "Copy file " << file.fileName() << ": " << QFile::copy(filePath, "items/" + file.fileName());
			refreshImages();
		}
	}
}

namespace AirCrash {
namespace Calypso {

PhotoThread::PhotoThread() : mInterrupted(false) {
}

PhotoThread::~PhotoThread() {
}

void PhotoThread::run() {
	QDir photoDir("items");
	QStringList imageList(photoDir.entryList(QStringList("*.*"), QDir::Files));
	cout << "Num Files: " << imageList.size() << "\n";
	for (QStringList::const_iterator it(imageList.begin()); it != imageList.end() && !mInterrupted; ++it) {
		const QString& fileName(*it);
		cout << "Loading " << fileName.toStdString() << "\n";
		QIcon icon(QPixmap("items/" + fileName));
		emit imageReady(icon, fileName);
	}
}

void PhotoThread::interrupt() {
	mInterrupted = true;
}

InsertItemThread::InsertItemThread() {
}

InsertItemThread::~InsertItemThread() {
}

void InsertItemThread::insertItem(const QString& summary, const QString& imagePath, int friday, int saturday, int sunday, bool jackpot) {
	mSummary = summary;
	mImagePath = imagePath;
	mFriday = friday;
	mSaturday = saturday;
	mSunday = sunday;
	mJackpot = jackpot;

	start();
}

void InsertItemThread::insertItem(const QString& summary, const QImage& image, int friday, int saturday, int sunday, bool jackpot) {
	mSummary = summary;
	mImage = image;
	mFriday = friday;
	mSaturday = saturday;
	mSunday = sunday;
	mJackpot = jackpot;

	start();
}

void InsertItemThread::run() {

	QImage image;

	if (mImagePath.isEmpty()) {
		image = mImage;
	} else {
		image = QImage("items/" + mImagePath);
	}
	
	image = image.scaled(Config::get("Image", "maxSize").toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation);

	QByteArray imageData;
	QBuffer buffer(&imageData);
	buffer.open(QIODevice::WriteOnly);
	image.save(&buffer, "PNG");

	QSqlTableModel model;
	model.setTable("Items");
	model.setEditStrategy(QSqlTableModel::OnManualSubmit);
	QSqlRecord record = model.record();

	record.setValue("Summary", mSummary);
	record.setValue("Friday", mFriday);
	record.setValue("Saturday", mSaturday);
	record.setValue("Sunday", mSunday);
	record.setValue("Image", imageData);
	record.setValue("Jackpot", mJackpot);

	if (!model.insertRecord(-1, record)) {
		QMessageBox::warning(0, "ERROR", "Er is iet mislopen:\n" + model.lastError().text());
	}
	if (!model.submitAll()) {
		QMessageBox::warning(0, "ERROR", "Er is iet mislopen:\n" + model.lastError().text());
	}

	QFile::remove("items/" + mImagePath);
	if (Config::get("Settings", "backupImages").toBool()) {
		QString imageName("backup/" + model.query().lastInsertId().toString() + ".png");
		image.save(imageName, "PNG");
	}

	emit itemInserted();
}

GenerateCodesThread::GenerateCodesThread() {
}

GenerateCodesThread::~GenerateCodesThread() {
}

void GenerateCodesThread::run() {

	QSqlQuery query;
	if (!query.exec("DELETE FROM Codes")) {
		qDebug() << "Error: " << query.lastError().text();
	}

	QVector<int> itemsFriday,
		itemsSaturday,
		itemsSunday;

	QSqlTableModel codeModel;
	codeModel.setTable("Codes");
	codeModel.setEditStrategy(QSqlTableModel::OnManualSubmit);

	QSqlTableModel itemModel;
	itemModel.setTable("Items");
	itemModel.select();

	for (int t(0); t < itemModel.rowCount(); ++t) {
		QSqlRecord record(itemModel.record(t));
		for (int x(0); x < record.value("Friday").toInt(); ++x) {
			itemsFriday.push_back(record.value("Id").toInt());
		}
		for (int x(0); x < record.value("Saturday").toInt(); ++x) {
			itemsSaturday.push_back(record.value("Id").toInt());
		}
		for (int x(0); x < record.value("Sunday").toInt(); ++x) {
			itemsSunday.push_back(record.value("Id").toInt());
		}
	}

	random_shuffle(itemsFriday.begin(), itemsFriday.end());
	random_shuffle(itemsSaturday.begin(), itemsSaturday.end());
	random_shuffle(itemsSunday.begin(), itemsSunday.end());

	foreach(int itemId, itemsFriday) {
		QSqlRecord record(codeModel.record());
		record.setValue("ItemId", itemId);
		record.setValue("Day", 1);
		codeModel.insertRecord(-1, record);
	}
	foreach(int itemId, itemsSaturday) {
		QSqlRecord record(codeModel.record());
		record.setValue("ItemId", itemId);
		record.setValue("Day", 2);
		codeModel.insertRecord(-1, record);
	}
	foreach(int itemId, itemsSunday) {
		QSqlRecord record(codeModel.record());
		record.setValue("ItemId", itemId);
		record.setValue("Day", 3);
		codeModel.insertRecord(-1, record);
	}
	codeModel.submitAll();

	emit codesGenerated();
}

}
}